/*
 * @Author: hongbin
 * @Date: 2023-06-08 21:49:19
 * @LastEditors: hongbin
 * @LastEditTime: 2023-06-10 09:15:58
 * @Description: three-dimensional font 3D文字 置换贴图 alpha贴图
 */
import { FC } from "react";
import * as THREE from "three";
import { ThreeHelper } from "@/ThreeHelper";
import Layout from "@/components/Three/Layout";

interface IProps {}

const destroyEvent = [] as VoidFunction[];

const Index: FC<IProps> = () => {
    return (
        <Layout
            seoTitle={"立体文字"}
            init={init}
            destroy={() => destroyEvent.forEach((destroy) => destroy())}
        />
    );
};

export default Index;

async function init(helper: ThreeHelper) {
    helper.addStats();
    helper.camera.position.set(0, 0, 10);
    helper.frameByFrame();
    helper.addGUI();
    helper.useRoomEnvironment(true);
    // helper.useSkyEnvironment();
    helper.initLights();

    new CanvasFontMesh("🌈", new THREE.Vector3(-2, 0, 0));
    new CanvasFontMesh("👏");
    new CanvasFontMesh("💩", new THREE.Vector3(2, 0, 0));
    new CanvasFontMesh("🎉", new THREE.Vector3(4, 0, 0));
    new CanvasFontMesh("T", new THREE.Vector3(0, -2, 0));
    new CanvasFontMesh("H", new THREE.Vector3(2, -2, 0));
    new CanvasFontMesh("R", new THREE.Vector3(4, -2, 0));
    new CanvasFontMesh("E", new THREE.Vector3(6, -2, 0));
    new CanvasFontMesh("E", new THREE.Vector3(8, -2, 0));
    // document.body.appendChild(c.canvas);
    // destroyEvent.push(() => {
    //     document.body.removeChild(c.canvas);
    // });
}

class Canvas {
    canvas: HTMLCanvasElement = document.createElement("canvas");
    protected ctx: CanvasRenderingContext2D = this.canvas.getContext("2d")!;
    public texture = new THREE.Texture(this.canvas);

    constructor(font: string) {
        const accuracy = 1;
        this.canvas.width = 220 * accuracy;
        this.canvas.height = 240 * accuracy;

        this.ctx.fillStyle = "#000";
        this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);

        this.ctx.shadowBlur = 5 * accuracy;
        this.ctx.shadowColor = "#ffffff";

        //绘制文字
        this.ctx.font = `${200 * accuracy}px Georgia`;
        this.ctx.textAlign = "center";
        this.ctx.fillStyle = "#ffffff";
        this.ctx.fillText(font, 110 * accuracy, 190 * accuracy);

        this.texture.needsUpdate = true;
        this.texture.colorSpace = THREE.SRGBColorSpace;

        this.canvas.style.position = "fixed";
        this.canvas.style.zIndex = "12";
        this.canvas.style["border"] = "1px solid";
    }
}

class CanvasFontMesh extends Canvas {
    mesh: THREE.Mesh<THREE.PlaneGeometry, THREE.MeshStandardMaterial>;

    constructor(font: string, position = new THREE.Vector3()) {
        super(font);

        const material = new THREE.MeshStandardMaterial({
            map: this.texture,
            // alphaMap: this.texture,
            // transparent: true,
            displacementMap: this.texture,
            displacementScale: 0.5,
            side: THREE.DoubleSide,
        });

        material.onBeforeCompile = (shader) => {
            shader.fragmentShader = shader.fragmentShader.replace(
                "#include <dithering_fragment>",
                `
                #include <dithering_fragment>
                if(gl_FragColor.r < 0.3){
                   discard;
                }
            `
            );
        };

        this.mesh = new THREE.Mesh(
            new THREE.PlaneGeometry(2, 2, 80, 80),
            material
        );

        this.mesh.position.copy(position);
        ThreeHelper.instance.add(this.mesh);
    }
}
